#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sharp-dynamicarray.h> 
#include <sharp-alloc.h>

bool sharp_dynamicarray_init(sharp_dynamicarray **list, size_t membersize){
    sharp_dynamicarray *tmpList;
    
    if(membersize < 0)
        return false;
    if((tmpList = (sharp_dynamicarray*)sharp_malloc(sizeof(sharp_dynamicarray)))
        == NULL)
        return false;
    tmpList->data = (void*)sharp_malloc(membersize*2);
    if(!tmpList->data){
        sharp_free(tmpList);
        return false;
    }
    tmpList->membersize = membersize;
    tmpList->length = 0;
    tmpList->size = 2;
    *list = tmpList;
    return true;
}

bool sharp_dynamicarray_append(sharp_dynamicarray **list, void **data){
    sharp_dynamicarray *tmpList;
    void *newData;
    
    tmpList = *list;
    if(tmpList->length >= tmpList->size){
        if(tmpList->size < 1){
            tmpList->size = 1;
        }
        newData = (void*)sharp_realloc(tmpList->data, 
            (tmpList->size << 1)*(tmpList->membersize));
        if(!newData)
            return false;
        tmpList->size <<= 1;
        tmpList->data = newData;
    }
    memcpy((void*)(((char*)tmpList->data)+(++tmpList->length)), *data,
            tmpList->membersize);
    return true;
}

bool sharp_dynamicarray_delete_last(sharp_dynamicarray **list, void **data){
    sharp_dynamicarray *tmpList;
    
    tmpList = *list;
    if(tmpList->length < 1)
        return false;
    if(data)
        memcpy(*data, (void*)(((char*)tmpList->data)+(--tmpList->length)),
            tmpList->membersize);
    else
        tmpList->length--;
    return true;
}

bool sharp_dynamicarray_clean(sharp_dynamicarray **list){
    if(!list)
        return false;
    return sharp_dynamicarray_resize(list, (*list)->length);
}

bool sharp_dynamicarray_resize(sharp_dynamicarray **list, int size){
    sharp_dynamicarray *tmpList;
    void **newData;
    
    tmpList = *list;
    newData = (void**)sharp_realloc(tmpList->data, size*(tmpList->membersize));
    if(!newData)
        return false;
    tmpList->data = newData;
    tmpList->size = size;
    return true;
}

bool sharp_dynamicarray_destroy(sharp_dynamicarray **list, 
    void (*destroy_data)(void *data)){
    int i, length;
    void *currentData;
    
    length = (*list)->length;
    currentData = (*list)->data;
    if(destroy_data)
        for(i = 0; i < length; i++){
            destroy_data(currentData++);
        }
    sharp_free((*list)->data);
    sharp_free(*list);
    return true;
}

bool sharp_dynamicarray_isempty(sharp_dynamicarray *list){
    return (list->length == 0);
}

int sharp_dynamicarray_length(sharp_dynamicarray *list){
    return list->length;
}